﻿using FunArts.EasyDevOps.Rcl.Repertories;
using FunArts.EasyDevOps.Shared.Models.Enums;
using FunArts.EasyDevOps.Shared.Models.SshClient.Command;
using FunArts.EasyDevOps.Shared.Models.SshClient.NginxClient;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FunArts.EasyDevOps.Rcl.Service.Impl
{
    /// <summary>
    /// Nginx管理服务
    /// </summary>
    public class RemoteNginxService: IRemoteNginxService
    {
        public ISshClientService SshClientService { get; set; }
        public INginxConfigRepertory NginxConfigRepertory { get; set; }

        public RemoteNginxService(ISshClientService sshClientService, INginxConfigRepertory nginxConfigRepertory)
        {
            SshClientService = sshClientService;
            NginxConfigRepertory = nginxConfigRepertory;
        }
        /// <summary>
        /// 获取当前配置
        /// </summary>
        /// <param name="configPath"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public NginxServerConfig GetCurrentConfig(string configPath = "/etc/nginx/conf.d/default")
        {
            CheckFileCommand checkFileCommand = new CheckFileCommand
            {
                FileName = configPath
            };
            var commandResult = SshClientService.ExecuteCommand(checkFileCommand);
            if (commandResult.Output == "false")
            {
                return new NginxServerConfig();
            }
            CatFileCommand catFileCommand = new CatFileCommand
            {
                FileName = configPath
            };
            commandResult = SshClientService.ExecuteCommand(catFileCommand);
            if (!string.IsNullOrEmpty(commandResult.Error))
            {
                return new NginxServerConfig();
            }

            return NginxConfigRepertory.ParseConfig(commandResult.Output);
        }
        /// <summary>
        /// 更新配置
        /// </summary>
        /// <param name="config"></param>
        /// <param name="configPath"></param>
        /// <param name="progressCallback"></param>
        /// <returns></returns>
        public async Task UpdateConfig(NginxServerConfig config, string configPath = "/etc/nginx/conf.d/default", Action<double> progressCallback = null)
        {
            var configText = NginxConfigRepertory.GenerateConfig(config);
            //上传文件
            await SshClientService.UploadFileAsync(Encoding.UTF8.GetBytes(configText), configPath, progressCallback);

            //using (var scp = new ScpClient(_sshClient.ConnectionInfo))
            //{
            //    scp.Connect();
            //    scp.Upload(new FileInfo(tempFile), $"/tmp/nginx_temp.conf");
            //}

            //// 移动文件到正确位置并设置权限
            //var command = _sshClient.RunCommand($"sudo mv /tmp/nginx_temp.conf {configPath} && sudo chown root:root {configPath} && sudo chmod 644 {configPath}");
            //if (!string.IsNullOrEmpty(command.Error))
            //    throw new Exception($"Error updating config: {command.Error}");
            //设置文件权限
            RootFileCommand rootFileCommand = new RootFileCommand
            {
                FileName = configPath
            };
            var linuxCommandResult = SshClientService.ExecuteCommand(rootFileCommand);

            // 测试并重新加载配置
            NginxCommand nginxCommand = new NginxCommand()
            {
                CommandType = NginxCommandTypeEnum.Test
            };
            linuxCommandResult = SshClientService.ExecuteCommand(nginxCommand);
            if(!linuxCommandResult.Error.Contains("test is successful"))
            {
                throw new Exception($"Nginx配置测试失败: {linuxCommandResult.Error}");
            }
            nginxCommand.CommandType = NginxCommandTypeEnum.Reload;
            var reloadResult = SshClientService.ExecuteCommand(nginxCommand);
            linuxCommandResult = SshClientService.ExecuteCommand(nginxCommand).CheckAndThrowErr();

            //开放端口
            FirewallCommand firewallCommand = new FirewallCommand() { FirewallCommandType = FirewallCommandTypeEnum.Allow, Port = config.ListenPort.ToString() };
            SshClientService.ExecuteCommand(firewallCommand);
            //重载防火墙
            firewallCommand.FirewallCommandType = FirewallCommandTypeEnum.Reload;
            SshClientService.ExecuteCommand(firewallCommand);
        }
    }
}
